package com.sbtr.util;

import org.apache.commons.lang3.StringEscapeUtils;
import org.junit.Test;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.security.MessageDigest;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <p>Title: 字符串相关处理类</p>
 * @version 1.0
 */
public class StringHelper {

    /**
     * 字符串对像为null转换为""
     * @param strIn 字符串对象
     * @return Sring
     */
    public static String null2String(Object strIn) {
        return strIn == null ? "" : "" + strIn;
    }

    /**
     * 字符串对象为null转换为赋默认值
     * @param strIn 字符串对象
     * @param  defstr 默认值
     * @return Sring
     */
    public static String null2String(Object strIn, String defstr) {
        return strIn == null ? defstr : "" + strIn;
    }

    /**
     * 字符串gbk编码转iso编码
     * @param s 字符串
     * @return Sring
     */
    public static String GBK2ISO(String s) {
        try {
            return new String(s.getBytes("GBK"), "ISO8859_1");
        } catch (UnsupportedEncodingException ex) {
            return null;
        }
    }
    /**
     * 字符串iso编码转gbk编码
     * @param s 字符串
     * @return Sring
     */
    public static String ISO2GBK(String s) {
        try {
            return new String(s.getBytes("ISO8859_1"), "GBK");
        } catch (UnsupportedEncodingException ex) {
            return null;
        }
    }

    // 判断字符串是否为空或null
    public static boolean isNullOrEmpty(String str) {
        return str == null || str.trim().isEmpty();
    }

    /**
     * 判断字符串是否不为空
     *
     * @param str 字符串
     */
    public static boolean isNotEmpty(String str) {
        return !isEmpty(str);
    }

    /**
     * 判断两个字符串是否相等
     *
     * @param str1 字符串1
     * @param str2 字符串2
     * @return 如果两个字符串都为null或相等则返回true，否则返回false
     */
    public static boolean equals(String str1, String str2) {
        return str1 == null ? str2 == null : str1.equals(str2);
    }

    /**
     * 判断两个字符串是否相等（忽略大小写）
     *
     * @param str1 字符串1
     * @param str2 字符串2
     * @return 如果两个字符串都为null或相等（忽略大小写）则返回true，否则返回false
     */
    public static boolean equalsIgnoreCase(String str1, String str2) {
        return str1 == null ? str2 == null : str1.equalsIgnoreCase(str2);
    }

    // 将字符串中的驼峰命名法转为下划线命名法
    public static String camelCaseToUnderscore(String str) {
        return str.replaceAll("([A-Z])", "_$1").toLowerCase();
    }

    /**
     * 将字符串按照指定分隔符分割成数组
     *
     * @param str       字符串
     * @param separator 分隔符
     * @return 分割后的字符串数组，如果为null则返回null
     */
    public static String[] split(String str, String separator) {
        if (StringHelper.isNullOrEmpty(str)) {
            return new String[0];
        }
        return str.split(separator);
    }

    /**
     * 将字符串按照指定分隔符分割成集合
     *
     * @param str       字符串
     * @param separator 分隔符
     * @return 分割后的字符串集合，如果为null则返回null
     */
    public static List<String> splitToList(String str, String separator) {
        if (StringHelper.isNullOrEmpty(str)) {
            return new ArrayList<String>();
        }
        return Arrays.asList(str.split(separator));
    }

    // 将字符串按指定长度分割成字符串数组
    public static String[] splitByLength(String str, int length) {
        if (StringHelper.isNullOrEmpty(str)) {
            return new String[0];
        }
        int size = (int) Math.ceil((double) str.length() / length);
        String[] result = new String[size];
        for (int i = 0; i < size; i++) {
            int start = i * length;
            int end = Math.min(start + length, str.length());
            result[i] = str.substring(start, end);
        }
        return result;
    }


    /**
     * 判断字符串是否为数字
     *
     * @param str 待检查字符串
     * @return 如果字符串为数字则返回true，否则返回false
     */
    public static boolean isNumeric(String str) {
        // 如果字符串为null，直接返回false
        if (str == null) {
            return false;
        }
        try {
            // 尝试将字符串转为double类型，如果能转换成功则说明字符串为数字
            Double.parseDouble(str);
        } catch (NumberFormatException e) {
            // 如果转换失败则说明字符串不是数字
            return false;
        }
        return true;
    }

    /**
     * 字符串集合转换为数值型集合
     * @param strList
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T extends Number> List<T> convertStrToNumber(List<String> strList, Class<T> clazz) {
        if (strList == null || strList.size() == 0) {
            return null;
        }
        List<T> resultList = new ArrayList<T>(strList.size());
        for (String str:strList) {
            if (clazz == Integer.class) {
                resultList.add((T) Integer.valueOf(str));
            } else if (clazz == Double.class) {
                resultList.add((T) Double.valueOf(str));
            } else if (clazz == Float.class) {
                resultList.add((T) Float.valueOf(str));
            } else if (clazz == Long.class) {
                resultList.add((T) Long.valueOf(str));
            } else if (clazz == Short.class) {
                resultList.add((T) Short.valueOf(str));
            } else if (clazz == Byte.class) {
                resultList.add((T) Byte.valueOf(str));
            }
        }
        return resultList;
    }



    /**
     * 判断字符串是否为布尔值
     *
     * @param str 待检查字符串
     * @return 如果字符串为true或false则返回true，否则返回false
     */
    public static boolean isBoolean(String str) {
        // 如果字符串为null，直接返回false
        if (str == null) {
            return false;
        }
        return str.equalsIgnoreCase("true") || str.equalsIgnoreCase("false");
    }


    /**
     * 将字符串转换成Integer类型
     *
     * @param str 字符串
     * @return Integer
     */
    public static Integer strToInteger(String str) {
        return Integer.parseInt(str);
    }

    /**
     * 将字符串转换成Long类型
     *
     * @param str 字符串
     * @return Long
     */
    public static Long strToLong(String str) {
        return Long.parseLong(str);
    }

    /**
     * 将字符串转换成Double类型
     *
     * @param str 字符串
     * @return Double
     */
    public static Double strToDouble(String str) {
        return Double.parseDouble(str);
    }

    /**
     * 将字符串转换成Float类型
     *
     * @param str 字符串
     * @return Float
     */
    public static Float strToFloat(String str) {
        return Float.parseFloat(str);
    }

    /**
     * 将字符串转换成BigDecimal类型
     *
     * @param str 字符串
     * @return BigDecimal
     */
    public static BigDecimal strToBigDecimal(String str) {
        return new BigDecimal(str);
    }

    /**
     * 将字符串转换成Boolean类型
     *
     * @param str 字符串
     * @return Boolean
     */
    public static Boolean strToBoolean(String str) {
        return Boolean.parseBoolean(str);
    }

    /**
     * 将字符串转换成Date类型
     *
     * @param str     字符串
     * @param pattern 日期格式
     * @return Date
     * @throws ParseException
     */
    public static Date strToDate(String str, String pattern) throws ParseException {
        DateFormat dateFormat = new SimpleDateFormat(pattern);
        return dateFormat.parse(str);
    }

    /**
     * 判断字符串是否为日期格式
     *
     * @param str    待检查字符串
     * @param format 日期格式，例如"yyyy-MM-dd"
     * @return 如果字符串为日期格式则返回true，否则返回false
     */
    public static boolean isDate(String str, String format) {
        // 如果字符串或日期格式为null，直接返回false
        if (str == null || format == null) {
            return false;
        }
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        try {
            // 尝试将字符串按照指定的日期格式解析为Date对象，如果能解析成功则说明字符串为日期格式
            sdf.parse(str);
        } catch (ParseException e) {
            return false;
        }
        return true;
    }

    /**
     * 去除字符串中的空格
     *
     * @param str 待处理字符串
     * @return 去除空格后的字符串
     */
    public static String removeSpaces(String str) {
        // 如果字符串为null，直接返回null
        if (str == null) {
            return null;
        }
        // 使用正则表达式匹配所有空格，并替换为空字符串
        return str.replaceAll("\\s+", "");
    }

    /**
     * 去除字符串首尾的空格
     *
     * @param str 字符串
     * @return 去除空格后的字符串，如果为null则返回null
     */
    public static String trim(String str) {
        return str == null ? null : str.trim();
    }

    /**
     * 去除字符串中的特定字符
     *
     * @param str           待处理字符串
     * @param charsToRemove 要去除的字符，例如"abc"
     * @return 去除特定字符后的字符串
     */
    public static String removeChars(String str, String charsToRemove) {
        // 如果字符串或要去除的字符为null，直接返回null
        if (str == null || charsToRemove == null) {
            return null;
        }
        // 使用正则表达式匹配所有要去除的字符，并替换为空字符串
        return str.replaceAll("[" + charsToRemove + "]", "");
    }


    /**
     * 将字符串转为驼峰命名法
     *
     * @param str 待处理字符串
     * @return 转换后的字符串
     */
    public static String toCamelCase(String str) {
        // 如果字符串为null，直接返回null
        if (str == null) {
            return null;
        }
        String[] words = str.split("[^a-zA-Z0-9]+"); // 使用正则表达式将字符串按照非字母数字字符分割为单词数组
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < words.length; i++) {
            String word = words[i];
            if (i == 0) {
                // 第一个单词不需要大写首字母
                sb.append(word.toLowerCase());
            } else {
                // 后续单词需要大写首字母
                sb.append(Character.toUpperCase(word.charAt(0)));
                sb.append(word.substring(1).toLowerCase());
            }
        }
        return sb.toString();
    }

    /**
     * 将字符串转为下划线命名法
     *
     * @param str 待处理字符串
     * @return 转换后的字符串
     */
    public static String toUnderscoreCase(String str) {
        // 如果字符串为null，直接返回null
        if (str == null) {
            return null;
        }
        String[] words = str.split("[^a-zA-Z0-9]+"); // 使用正则表达式将字符串按照非字母数字字符分割为单词数组
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < words.length; i++) {
            String word = words[i];
            if (i == 0) {
                // 第一个单词不需要加下划线
                sb.append(word.toLowerCase());
            } else {
                // 后续单词需要加下划线
                sb.append("_");
                sb.append(word.toLowerCase());
            }
        }
        return sb.toString();
    }

    /**
     * 将字符串转为首字母大写形式
     *
     * @param str 待处理字符串
     * @return 转换后的字符串
     */
    public static String capitalize(String str) {
        // 如果字符串为null，直接返回null
        if (str == null) {
            return null;
        }
        // 将第一个字符转为大写字母，然后再将剩余字符拼接上
        return Character.toUpperCase(str.charAt(0)) + str.substring(1);
    }

    /**
     * 字符串根据某个字符分隔为字符串数组
     * @param strIn 字符串
     * @param  strDim  分隔符
     * @return 字符串数组ArraryList
     */
    public static ArrayList string2ArrayList2(String strIn, String strDim) {
        strIn = null2String(strIn);
        strDim = null2String(strDim);
        ArrayList strList = new ArrayList();

        String[] sr2 = strIn.split(strDim);
        for (int i = 0; i < sr2.length; i++) {
            strList.add(null2String(sr2[i]));
        }
        if (strIn.endsWith(strDim))
            strList.add("");

        return strList;
    }

    public static String padString(String strIn,int length,char padChar){
        if(strIn.length()>=length)
            return strIn;
        int needPadLen = length - strIn.length();
        for(int i=0;i<=needPadLen;i++){
            strIn = padChar+strIn;
        }
        return strIn;
    }

    public static Map string2Map(String strIn, String strDim) {
        Map map = new HashMap();
        List list = string2ArrayList(strIn, strDim);
        Iterator it = list.iterator();
        while (it.hasNext()) {
            String str = (String) it.next();
            map.put(str.substring(0, str.indexOf("=")).trim(), str.substring(str.indexOf("=") + 1).trim());
        }
        return map;
    }

    /**
     * 字符串根据某个字符分隔为字符串数组
     * @param strIn 字符串
     * @param  strDim  分隔符
     * @return 字符串数组ArraryList
     */
    public static ArrayList string2ArrayList(String strIn, String strDim) {
        return string2ArrayList(strIn, strDim, false);
    }

    /**
     * 字符串根据某个字符分隔为字符串数组
     * @param strIn 字符串
     * @param  strDim  分隔符
     * @param  bReturndim
     * @return 字符串数组ArraryList
     */
    public static ArrayList string2ArrayList(String strIn, String strDim, boolean bReturndim) {
        strIn = null2String(strIn);
        strDim = null2String(strDim);
        ArrayList strList = new ArrayList();
        StringTokenizer strtoken = new StringTokenizer(strIn, strDim, bReturndim);
        while (strtoken.hasMoreTokens()) {
            strList.add(strtoken.nextToken());
        }
        return strList;
    }
    /**
     * 字符串根据某个字符分隔为字符串数组
     * @param strIn 字符串
     * @param  strDim  分隔符
     * @return 字符串数组String[]
     */
    public static String[] string2Array(String strIn, String strDim) {
        return string2Array(strIn, strDim, false);
    }

    /**
     * 字符串根据某个字符分隔为字符串数组
     * @param strIn 字符串
     * @param  strDim  分隔符
     * @param  bReturndim
     * @return 字符串数组String[]
     */
    public static String[] string2Array(String strIn, String strDim, boolean bReturndim) {
        ArrayList strlist = string2ArrayList(strIn, strDim, bReturndim);
        int strcount = strlist.size();
        String[] strarray = new String[strcount];
        for (int i = 0; i < strcount; i++) {
            strarray[i] = (String) strlist.get(i);
        }
        return strarray;
    }

    /**
     * 对象是否包含某个对象
     *
     * @param a 源对象
     * @param s 被包含对象
     * @return true 包含 false 不包含
     */
    public static boolean contains(Object a[], Object s) {
        if (a == null || s == null) {
            return false;
        }
        for (int i = 0; i < a.length; i++) {
            if (a[i] != null && a[i].equals(s)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 替换字符
     * @param s 字符串
     * @param c1 被替换的字符
     * @param c2 替换字符
     * @return String
     */
    public static String replaceChar(String s, char c1, char c2) {
        if (s == null) {
            return s;
        }

        char buf[] = s.toCharArray();
        for (int i = 0; i < buf.length; i++) {
            if (buf[i] == c1) {
                buf[i] = c2;
            }
        }
        return String.valueOf(buf);
    }


    /**
     * 替换字符串
     * @param strSource
     * @param strFrom
     */
    public static String replaceString(String strSource, String strFrom, String strTo) {
        if (strSource == null) {
            return strSource;
        }
        int i = 0;
        if ((i = strSource.indexOf(strFrom, i)) >= 0 && strTo != null) {
            char[] cSrc = strSource.toCharArray();
            char[] cTo = strTo.toCharArray();
            int len = strFrom.length();
            StringBuffer buf = new StringBuffer(cSrc.length);
            buf.append(cSrc, 0, i).append(cTo);
            i += len;
            int j = i;
            while ((i = strSource.indexOf(strFrom, i)) > 0) {
                buf.append(cSrc, j, i - j).append(cTo);
                i += len;
                j = i;
            }
            buf.append(cSrc, j, cSrc.length - j);
            return buf.toString();
        }
        return strSource;
    }
    /**
     * 随机生成动态密码
     *
     * @param passrule 生成规则
     * @param length 生成长度
     * @return String
     */
    public static String passwordBuilder(String passrule, int length) //随机生成动态密码
    {
        String str = "";
        int prule = Integer.valueOf(passrule).intValue();
        String[] arr = null;
        switch (prule) {
            case 0:
                String[] tmp_arr = { "A", "B", "D", "E", "F", "G", "H", "J", "L", "M", "N", "Q", "R", "T", "Y", "a", "d",
                        "e", "f", "g", "h", "i", "j", "m", "n", "r", "t", "u", "y" }; //大写小写
                arr = tmp_arr;
                break;
            case 1:
                String[] tmp_arr1 = { "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "D", "E", "F", "G", "H", "J", "L",
                        "M", "N", "Q", "R", "T", "Y" }; //大写数字
                arr = tmp_arr1;
                break;
            case 2:
                String[] tmp_arr2 = { "2", "3", "4", "5", "6", "7", "8", "9", "a", "d", "e", "f", "g", "h", "i", "j", "m",
                        "n", "r", "t", "u", "y" }; //小写数字
                arr = tmp_arr2;
                break;
            case 3:
                String[] tmp_arr3 = { "2", "3", "4", "5", "6", "7", "8", "9", "a", "d", "e", "f", "g", "h", "i", "j", "m",
                        "n", "r", "t", "u", "y", "A", "B", "D", "E", "F", "G", "H", "J", "L", "M", "N", "Q", "R", "T", "Y" }; //大写小写数字
                arr = tmp_arr3;
                break;
            case 4:
                String[] tmp_arr4 = { "A", "B", "D", "E", "F", "G", "H", "J", "L", "M", "N", "Q", "R", "T", "Y" }; //大写数字
                arr = tmp_arr4;
                break;
            case 5:
                String[] tmp_arr5 = { "a", "d", "e", "f", "g", "h", "i", "j", "m", "n", "r", "t", "u", "y" }; //小写数字
                arr = tmp_arr5;
                break;
            case 6:
                String[] tmp_arr6 = { "2", "3", "4", "5", "6", "7", "8", "9", }; //大写小写数字
                arr = tmp_arr6;
                break;
            default:
                String[] tmp_arrd = { "2", "3", "4", "5", "6", "7", "8", "9", "a", "d", "e", "f", "g", "h", "i", "j", "m",
                        "n", "r", "t", "u", "y" }; //大写小写数字
                arr = tmp_arrd;
                break;
        }

        Random rd = new Random();
        while (str.length() < length) {

            String temp = arr[rd.nextInt(arr.length)];
            if (str.indexOf(temp) == -1) {
                str += temp;
            }
        }
        return str;
    }

    /**
     * 字符串替换，仅替换第一次出现的字符串
     * @param sou 源字符串
     * @param s1 被替换的字符串
     * @param s2 替换字符串
     * @return String
     */
    public static String replaceStringFirst(String sou, String s1, String s2) {
        int idx = sou.indexOf(s1);
        if (idx < 0) {
            return sou;
        }
        return sou.substring(0, idx) + s2 + sou.substring(idx + s1.length());
    }

    /**
     * 字符串区域替换
     *
     * 注: StringHelper.replaceRange("this is a test sentense,Look at
     * this!","test","look ","stone!",false) ???? this is a stone!at this!
     * StringHelper.replaceRange("this is a test sentense,Look at
     * this!","test","look ","stone!",true) ???? this is a stone! sentense,Look
     * at this!
     * @param sentence 源字符串
     * @param oStart 替换区域开始字符串
     * @param oEnd  替换区域结束字符中
     * @param rWord 替换字符串
     * @param matchCase 是否忽略大小写
     * @return String
     *
     */
    public static String replaceRange(String sentence, String oStart, String oEnd, String rWord, boolean matchCase) {
        int sIndex = -1;
        int eIndex = -1;
        if (matchCase) {
            sIndex = sentence.indexOf(oStart);
        } else {
            sIndex = sentence.toLowerCase().indexOf(oStart.toLowerCase());
        }
        if (sIndex == -1 || sentence == null || oStart == null || oEnd == null || rWord == null) {
            return sentence;
        } else {
            if (matchCase) {
                eIndex = sentence.indexOf(oEnd, sIndex);
            } else {
                eIndex = sentence.toLowerCase().indexOf(oEnd.toLowerCase(), sIndex);
            }
            String newStr = null;
            if (eIndex > -1) {
                newStr = sentence.substring(0, sIndex) + rWord + sentence.substring(eIndex + oEnd.length());
            } else {
                newStr = sentence.substring(0, sIndex) + rWord + sentence.substring(sIndex + oStart.length());
            }
            return replaceRange(newStr, oStart, oEnd, rWord, matchCase);
        }
    }
    /**
     * 识别是否为空
     * @param str 源字符串
     * @return boolean
     */
    public static boolean isEmpty(String str) {
        return str == null || str == "null" || str.equalsIgnoreCase("null") || str.equals("[]") || str.length() == 0;
    }


    /**
     * 判断字段不为空，但是为空字符串（""）
     * @param str 源字符串
     * @return boolean
     */
    public static boolean isStr(String str) {
        return null != str && str.equals("");
    }


    /**
     * 识别是否32位id
     * @param str 源字符串
     * @return boolean
     */
    public static boolean isID(String str) {
        return !isEmpty(str.trim()) && str.trim().length() == 32
                || NumberHelper.string2Int(StringHelper.null2String(str.trim())) != -1;
    }

    /**
     * 字符串对象为空转为null
     * @param str 源字符串
     * @return String
     */
    public static String trimToNull(Object str) {
        if (str == null)
            return null;
        return trimToNull((String) str);
    }

    /**
     * 格式化并识别布尔型变量如:y为true,1为true 等
     * @param param 被格式化字符
     * @return boolean
     */
    public static boolean parseBoolean(String param) {
        if (isEmpty(param)) {
            return false;
        }
        switch (param.charAt(0)) {
            case '1':
            case 'y':
            case 'Y':
            case 't':
            case 'T':
                return true;
        }
        return false;
    }
    /**
     * 获得某个长度的随机串
     * @param length 附机串长度
     * @return String
     */
    public static String getRandomStr(int length) {
        String psd = "";
        char c;
        int i;
        int isnum = 0;
        for (int j = 0; j < length; j++) {
            if (isnum == 0) {
                isnum = 1;
                c = (char) (Math.random() * 26 + 'a');
                psd += c;
            } else {
                isnum = 0;
                c = (char) (Math.random() * 10 + '0');
                psd += c;
            }
        }
        return psd;
    }
    /**
     * 字符转义
     * @param s 源字符串
     * @return String
     */
    public static String fromDB(String s) {
        char c[] = s.toCharArray();
        char ch;
        int i = 0;
        StringBuffer buf = new StringBuffer();

        while (i < c.length) {
            ch = c[i++];
            if (ch == '\"') {
                buf.append("\\\"");
            } else {
                buf.append(ch);
            }
        }
        return buf.toString();
    }
    /**
     * 字符串对象数组转为字符串
     * @param strIn 字符串数组
     * @param  strDim  分隔符
     * @return string
     */
    public static String Array2String(Object[] strIn, String strDim) {
        StringBuffer str = new StringBuffer();
        int len = strIn.length;
        for (int i = 0; i < len; i++) {
            str.append((i == 0) ? strIn[i] : strDim + strIn[i]);
        }
        return str.toString();
    }
    /**
     * 字符串数组转为字符串
     * @param strIn 字符串数组
     * @param  strDim  分隔符
     * @return string
     */
    public static String Array2String(String[] strIn, String strDim) {
        StringBuffer strOut = new StringBuffer();
        for (String tempStr : strIn) {
            strOut.append(tempStr).append(strDim);
        }
        if (strOut.length() > 0)
            strOut.delete(strOut.lastIndexOf(strDim), strOut.length());
        return strOut.toString();
    }
    /**
     * ArrayList数组转为字符串
     * @param strIn 字符串数组
     * @param  strDim  分隔符
     * @return string
     */
    public static String ArrayList2String(ArrayList strIn, String strDim) {
        return List2String(strIn, strDim);
    }
    /**
     * List数组转为字符串
     * @param strIn 字符串数组
     * @param  strDim  分隔符
     * @return string
     */
    public static String List2String(List strIn, String strDim) {
        StringBuffer strOut = new StringBuffer();
        for (Object o : strIn) {
            strOut.append(o.toString()).append(strDim);
        }
        if (strOut.length() > 0)
            strOut.delete(strOut.lastIndexOf(strDim), strOut.length());
        return strOut.toString();
    }

    public static String fillValuesToString(String str, Hashtable ht) {
        return fillValuesToString(str, ht, '$');
    }

    public static String fillValuesToString(String str, Hashtable ht, char VARIABLE_PREFIX) {

        char TERMINATOR = '\\';

        if (str == null || str.length() == 0 || ht == null) {
            return str;
        }

        char s[] = str.toCharArray();
        char ch;
        int i = 0;
        String vname;
        StringBuffer buf = new StringBuffer();

        ch = s[i];
        while (true) {
            if (ch == VARIABLE_PREFIX) {
                vname = "";
                if (++i < s.length) {
                    ch = s[i];
                } else {
                    break;
                }
                while (true) {
                    if (ch != '_' && ch != '-' && !Character.isLetterOrDigit(ch)) {
                        break;
                    }
                    vname += ch;
                    if (++i < s.length) {
                        ch = s[i];
                    } else {
                        break;
                    }
                }

                if (vname.length() != 0) {
                    String vval = (String) ht.get(vname);
                    if (vval != null) {
                        buf.append(vval);
                    }
                }
                if (vname.length() != 0 && ch == VARIABLE_PREFIX) {
                    continue;
                }
                if (ch == TERMINATOR) {
                    if (++i < s.length) {
                        ch = s[i];
                    } else {
                        break;
                    }
                    continue;
                }
                if (i >= s.length) {
                    break;
                }
            }

            buf.append(ch);
            if (++i < s.length) {
                ch = s[i];
            } else {
                break;
            }
        }
        return buf.toString();
    }
    /**
     * 将多个带,号的id数据转化为'id',数据
     * @param ids 字符串
     * @return string
     */
    public static String formatMutiIDs(String ids) {
        String ret = "";
        ArrayList arrayids = string2ArrayList(ids, ",");
        for (int i = 0; i < arrayids.size(); i++) {
            String _id = null2String(String.valueOf(arrayids.get(i))).trim();
            if (StringHelper.isEmpty(_id))
                continue;
            if (isID(_id)) {
                ret += ",'" + _id + "'";
            }
        }
        if (!ret.equals(""))
            return ret.substring(1);
        else
            return "''";
    }

    /**
     * 从aids中剔除bids中的所有id
     * */
    public static String removeIDs(String aids, String bids) {
        ArrayList arrayids = string2ArrayList(bids, ",");
        for (int i = 0; i < arrayids.size(); i++) {
            String _id = null2String(String.valueOf(arrayids.get(i))).trim();
            if (isID(_id)) {
                aids = aids.replaceAll(_id, "");
            }
        }
        return formatMutiIDs(aids);
    }

    public static String lift(String arg, int length) {
        int sLength = arg.trim().length();
        if (length < 1 || length > sLength) {
            return arg.trim();
        } else {
            return arg.trim().substring(0, length);
        }

    }
    /**
     * 字符串格式化，一般用于url
     * */
    public static String getDecodeStr(String strIn) {
        if (strIn == null)
            return "";
        String strTemp = "";
        for (int i = 0; i < strIn.length(); i++) {
            char charTemp = strIn.charAt(i);
            switch (charTemp) {
                case 124: // '~'
                    String strTemp2 = strIn.substring(i + 1, i + 3);
                    strTemp = strTemp + (char) Integer.parseInt(strTemp2, 16);
                    i += 2;
                    break;

                case 94: // '^'
                    String strTemp3 = strIn.substring(i + 1, i + 5);
                    strTemp = strTemp + (char) Integer.parseInt(strTemp3, 16);
                    i += 4;
                    break;

                default:
                    strTemp = strTemp + charTemp;
                    break;
            }
        }

        return strTemp;
    }
    /**
     * 字符串反格式化，一般用于url
     * */
    public static String getEncodeStr(String strIn) {
        if (strIn == null)
            return "";
        String strOut = "";
        for (int i = 0; i < strIn.length(); i++) {
            int iTemp = strIn.charAt(i);
            if (iTemp > 255) {
                String strTemp2 = Integer.toString(iTemp, 16);
                for (int iTemp2 = strTemp2.length(); iTemp2 < 4; iTemp2++)
                    strTemp2 = "0" + strTemp2;

                strOut = strOut + "^" + strTemp2;
            } else {
                if (iTemp < 48 || iTemp > 57 && iTemp < 65 || iTemp > 90 && iTemp < 97 || iTemp > 122) {
                    String strTemp2 = Integer.toString(iTemp, 16);
                    for (int iTemp2 = strTemp2.length(); iTemp2 < 2; iTemp2++)
                        strTemp2 = "0" + strTemp2;

                    strOut = strOut + "|" + strTemp2;
                } else {
                    strOut = strOut + strIn.charAt(i);
                }
            }
        }

        return strOut;
    }


    public static String getfloatToString(String value) {
        int index = value.indexOf("E");
        if (index == -1) {
            return value;
        }

        int num = Integer.parseInt(value.substring(index + 1, value.length()));
        value = value.substring(0, index);
        index = value.indexOf(".");
        value = value.substring(0, index) + value.substring(index + 1, value.length());
        String number = value;
        if (value.length() <= num) {
            for (int i = 0; i < num - value.length(); i++) {
                number += "0";
            }
        } else {
            number = number.substring(0, num + 1) + "." + number.substring(num + 1) + "0";
        }
        return number;
    }
    /**
     * 浮点字符串保留两位小数
     * */
    public static String getfloatToString2(String value) { //保留两位小数
        value = getfloatToString(value);
        int index = value.indexOf(".");
        if (index == -1)
            return value;
        String value1 = value.substring(0, index);
        String value2 = value.substring(index + 1, value.length()) + "00";
        if (Integer.parseInt(value2.substring(0, 2)) == 0)
            return value1;
        else
            return value1 + "." + value2.substring(0, 2);
    }
    /**
     * 数字字符串保留两位小数
     * */
    public static String numberFormat2(String value) { //保留两位小数
        double num = NumberHelper.string2Double(StringHelper.null2String(value), 0.0);
        DecimalFormat df = new DecimalFormat("0.00");
        return df.format(num);
    }
    /**
     * 双精度字符串保留两位小数
     * */
    public static String numberFormat2(Double value) { //保留两位小数
        double num = NumberHelper.string2Double(StringHelper.null2String(value), 0.0);
        DecimalFormat df = new DecimalFormat("0.00");
        return df.format(num);
    }
    /**
     * 双精度字符串保留两位小数
     * */
    public static String numberFormat2(double value) { //保留两位小数
        DecimalFormat df = new DecimalFormat("0.00");
        return df.format(value);
    }
    /**
     *获取服务器名（域名或IP地址）和端口号
     * */
    public static String getRequestHost(HttpServletRequest request) {
        if (request == null) {
            return "";
        } else {//获取服务器名（域名或IP地址）和端口号
            String serverHost = request.getServerName()+":"+request.getServerPort();
            return (null2String(serverHost)).trim();
        }
    }

    // 以 java 实现 escape  unescape
    private final static String[] hex = { "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0A", "0B", "0C",
            "0D", "0E", "0F", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1A", "1B", "1C", "1D", "1E",
            "1F", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2A", "2B", "2C", "2D", "2E", "2F", "30",
            "31", "32", "33", "34", "35", "36", "37", "38", "39", "3A", "3B", "3C", "3D", "3E", "3F", "40", "41", "42",
            "43", "44", "45", "46", "47", "48", "49", "4A", "4B", "4C", "4D", "4E", "4F", "50", "51", "52", "53", "54",
            "55", "56", "57", "58", "59", "5A", "5B", "5C", "5D", "5E", "5F", "60", "61", "62", "63", "64", "65", "66",
            "67", "68", "69", "6A", "6B", "6C", "6D", "6E", "6F", "70", "71", "72", "73", "74", "75", "76", "77", "78",
            "79", "7A", "7B", "7C", "7D", "7E", "7F", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8A",
            "8B", "8C", "8D", "8E", "8F", "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9A", "9B", "9C",
            "9D", "9E", "9F", "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "AA", "AB", "AC", "AD", "AE",
            "AF", "B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9", "BA", "BB", "BC", "BD", "BE", "BF", "C0",
            "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9", "CA", "CB", "CC", "CD", "CE", "CF", "D0", "D1", "D2",
            "D3", "D4", "D5", "D6", "D7", "D8", "D9", "DA", "DB", "DC", "DD", "DE", "DF", "E0", "E1", "E2", "E3", "E4",
            "E5", "E6", "E7", "E8", "E9", "EA", "EB", "EC", "ED", "EE", "EF", "F0", "F1", "F2", "F3", "F4", "F5", "F6",
            "F7", "F8", "F9", "FA", "FB", "FC", "FD", "FE", "FF" };
    private final static byte[] val = { 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
            0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
            0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x00,
            0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x0A, 0x0B,
            0x0C, 0x0D, 0x0E, 0x0F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
            0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
            0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
            0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
            0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
            0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
            0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
            0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
            0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
            0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
            0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F };
    /**
     * 字符串加密
     * */
    public static String escape(String s) {
        if (isEmpty(s))
            return "";
        StringBuffer sbuf = new StringBuffer();
        int len = s.length();
        for (int i = 0; i < len; i++) {
            int ch = s.charAt(i);
            if (ch == ' ') { // space : map to '+'
                sbuf.append('+');
            } else if ('A' <= ch && ch <= 'Z') { // 'A'..'Z' : as it was
                sbuf.append((char) ch);
            } else if ('a' <= ch && ch <= 'z') { // 'a'..'z' : as it was
                sbuf.append((char) ch);
            } else if ('0' <= ch && ch <= '9') { // '0'..'9' : as it was
                sbuf.append((char) ch);
            } else if (ch == '-' || ch == '_' // unreserved : as it was
                    || ch == '.' || ch == '!' || ch == '~' || ch == '*' || ch == '\'' || ch == '(' || ch == ')') {
                sbuf.append((char) ch);
            } else if (ch <= 0x007F) { // other ASCII : map to %XX
                sbuf.append('%');
                sbuf.append(hex[ch]);
            } else { // unicode : map to %uXXXX
                sbuf.append('%');
                sbuf.append('u');
                sbuf.append(hex[(ch >>> 8)]);
                sbuf.append(hex[(0x00FF & ch)]);
            }
        }
        return sbuf.toString();
    }
    /**
     * 字符串解密
     * */
    public static String unescape(String s) {
        if (isEmpty(s))
            return "";
        StringBuffer sbuf = new StringBuffer();
        int i = 0;
        int len = s.length();
        while (i < len) {
            int ch = s.charAt(i);
            if (ch == '+') { // + : map to ' '
                sbuf.append(' ');
            } else if ('A' <= ch && ch <= 'Z') { // 'A'..'Z' : as it was
                sbuf.append((char) ch);
            } else if ('a' <= ch && ch <= 'z') { // 'a'..'z' : as it was
                sbuf.append((char) ch);
            } else if ('0' <= ch && ch <= '9') { // '0'..'9' : as it was
                sbuf.append((char) ch);
            } else if (ch == '-' || ch == '_' // unreserved : as it was
                    || ch == '.' || ch == '!' || ch == '~' || ch == '*' || ch == '\'' || ch == '(' || ch == ')') {
                sbuf.append((char) ch);
            } else if (ch == '%') {
                int cint = 0;
                if ('u' != s.charAt(i + 1)) { // %XX : map to ascii(XX)
                    cint = (cint << 4) | val[s.charAt(i + 1)];
                    cint = (cint << 4) | val[s.charAt(i + 2)];
                    i += 2;
                } else { // %uXXXX : map to unicode(XXXX)
                    cint = (cint << 4) | val[s.charAt(i + 2)];
                    cint = (cint << 4) | val[s.charAt(i + 3)];
                    cint = (cint << 4) | val[s.charAt(i + 4)];
                    cint = (cint << 4) | val[s.charAt(i + 5)];
                    i += 5;
                }
                sbuf.append((char) cint);
            }
            i++;
        }
        return sbuf.toString();
    }

    /**
     * 转换第一个字母为大写
     * */
    public static String changeFirstLetter(String string) {
        if (string == null) {
            return null;
        } else {
            String c = string.substring(0, 1);
            String d = c.toUpperCase();
            String returnString = string.replaceFirst(c, d);
            return returnString;
        }

    }

    /**
     * Converts some important chars (int) to the corresponding html string
     */
    public static String conv2Html(int i) {
        if (i == '&')
            return "&amp;";
        else if (i == '<')
            return "&lt;";
        else if (i == '>')
            return "&gt;";
        else if (i == '"')
            return "&quot;";
        else
            return "" + (char) i;
    }

    /**
     * Converts a normal string to a html conform string
     */
    public static String conv2Html(String st) {
        StringBuffer buf = new StringBuffer();
        for (int i = 0; i < st.length(); i++) {
            buf.append(conv2Html(st.charAt(i)));
        }
        return buf.toString();
    }

    /**
     * 移除开头，结尾，或中间的逗号
     * @param oldstationids
     * @return
     */
    public static String removeComma(String oldstationids) {
        if (!isEmpty(oldstationids)) {
            if (oldstationids.indexOf(",,") != -1) {
                return oldstationids.replace(",,", ",");
            }
            if (oldstationids.lastIndexOf(",") == oldstationids.length()) {
                oldstationids = oldstationids.substring(0, oldstationids.lastIndexOf(","));
            }
            if (oldstationids.indexOf(",") == 1) {
                return oldstationids.substring(1);
            }
        }
        return oldstationids;
    }

    /**
     * 生成令牌
     * @param request
     * @return
     */
    public static String generateToken(HttpServletRequest request) {
        HttpSession session = request.getSession();
        try {
            byte id[] = session.getId().getBytes();
            byte now[] = new Long(System.currentTimeMillis()).toString().getBytes();
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(id);
            md.update(now);
            return (md.digest().toString());
        } catch (Exception e) {
            return (null);
        }
    }


    /**
     * 过滤字符串中的正则表达式关键词。
     * @param sText as String
     * @return String
     */
    public static String filterRegexpChar(String sText) {
        int size = sText.length();
        StringBuffer s = new StringBuffer();
        char ch = 0;
        for (int i = 0; i < size; i++) {
            ch = sText.charAt(i);
            switch (ch) {
                case '\\':
                case '^':
                case '$':
                case '*':
                case '(':
                case ')':
                case '[':
                case ']':
                case '{':
                case '}':
                case '+':
                case '?':
                case '.':
                    s.append("\\" + ch);
                    break;
                default:
                    s.append(ch);
            }
        }
        return s.toString();
    }

    public static String translateVelocity(String s) {
        s = s.replaceAll("<w:(\\w+)>([^<]*)</w:\\w+>", "#$1$2");
        return s;
    }

    /**
     * 过滤Sql中的\n,\r,'等关键字符
     * @param sql as String
     * @return String
     */
    public static String filterSqlChar(String sql) {
        if (sql.indexOf('\'') >= 0)
            sql = sql.replaceAll("'", "''");
        sql = sql.replaceAll("\\n", "\\\\n");
        sql = sql.replaceAll("\\r", "\\\\r");
        return sql;
    }

    public static String filterSqlChar(Object obj) {
        if(obj==null)
            return "";
        String sql = obj.toString().trim();
        if (sql.indexOf('\'') >= 0)
            sql = sql.replaceAll("'", "''");
        sql = sql.replaceAll("\\n", "\\\\n");
        sql = sql.replaceAll("\\r", "\\\\r");
        return sql;
    }

    /**
     *当原字符串位数不足时，用补足字符在字符串前补足指定的位数
     */
    public static String fillString(String str, int length, char c) {
        while (str.length() < length) {
            str += c;
        }
        return str;
    }

    public static String trimFirstAndLastChar(String null2String, String string) {
        // TODO Auto-generated method stub
        return null2String.replace(string, "");
    }


    /**
     * 判断对象是否为空
     *
     * @param str
     * @return
     */
    public static boolean isNotEmpty(Object str) {
        boolean flag = true;
        if (str != null && str != "null" && !str.equals("") && !str.equals("\"\"")) {
            if (str.toString().length() > 0) {
                flag = true;
            }
        } else {
            flag = false;
        }
        return flag;
    }



    /**
     * 将带逗号分隔符的字符串解析成多个id的list数组
     * @param ids
     * @return
     */
    public static List<String> idsToList(String ids){

        List<String> idList = new ArrayList<String>();
        if(StringHelper.isNotEmpty(ids)){
            for (String id1 : ids.split(",")) {
                if (StringUtils.hasLength(id1) && !id1.equals("undefined")) {
                    idList.add(id1.trim());
                }
            }
        }

        return idList;

    }

    /**
     * 根据传入的字符串数组进行拆分，判断Y；得到int值
     * @return
     */
    public static Integer[] getIntegerYandN(String str){
        Integer y = 0;
        Integer n = 0;

        String[] arr = str.split(",");
        for(String number:arr){
            if(number.equals("Y")){
                y += 1;
            }else{
                n += 1;
            }
        }
        Integer[] YAndNnumber = {y,n};
        return YAndNnumber;
    }

    /**
     * 去除传入字符串的前后空格
     * @return
     */
    public static String trimBlanks(String str) {
        if(StringHelper.isNotEmpty(str)){
            return str.trim();
        }else{
            return null;
        }
    }

    public static String trimNulls(String str) {
        if(StringHelper.isNotEmpty(str)){
            return str;
        }else{
            return "/";
        }
    }
    /**
     * 去除传入字符串的全部空格
     * @return
     */
    public static String trimAllBlanks(String str) {
        return str.replaceAll(" ", "");
    }

    /**
     * 根据传入的多个参数，判断是否为空或为空字符串，存在一个为空或者空字符串就返回true
     * @param args
     * @return
     */
    public static boolean isPropertysEmpty(String... args) {
        for(String s:args){
            if (null == s  || "".equals(s)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断传入的多个字符串是否为null或者""
     * @param str
     * @return
     */
    public static boolean isStrEmpty(String... str) {
        for(String s1:str){
            if (null == s1  || "".equals(s1)) {
                return true;
            }
        }
        return false;
    }

    // 判断文件后缀名，是否为txt文件
    public static boolean isTextFile(String fileName){

        int index = fileName.lastIndexOf(".");
        String suffix = fileName.substring(index);
        if(".txt".equals(suffix)){
            // 返回判断界结果
            return true;
        }
        return false;
    }
    /**
     * 检查是否存在重复信息
     * @param list
     * @param id
     * @return
     */
    public static boolean isUnique(List<String> list, String id) {

        int size = list.size();
        if(size>1){ // 编辑、新增情况
            return false;
        } else if(size==1){ // 新增情况
            if(StringHelper.isEmpty(id))
                return false;

            if(list.get(0).equals(id))
                return true; // 当前对象编辑

            return false; // 其他对象编辑
        } else{
            return true;
        }
    }

    /**
     * 根据当前的部分元素移除原始字符串的含有的部分元素
     * @param oldStr
     * @param delStr
     * @return
     */
    public static String replaceStr(String oldStr, String delStr){

        if(StringHelper.isEmpty(oldStr))
            return oldStr;

        oldStr = oldStr.replace(delStr, "");

        String[] str2 = oldStr.split(",");
        String resultStr = "";
        for(int j=0; j<str2.length; j++){
            resultStr += str2[j]+",";
        }

        return  resultStr.substring(0,resultStr.length()-1);//去除最后一个逗号；;
    }

    // 判断文件后缀名是否为Excel文件
    public static boolean isExcelFile(String fileName){

        int index = fileName.lastIndexOf(".");
        String suffix = fileName.substring(index);
        if(".xlsx".equals(suffix) || ".xls".equals(suffix)){
            return true;
        }
        return false;
    }

    /**
     * 得到改变后的文件名称
     * @param fileName
     * @return
     */
    public static String getNewFileName(String fileName){
        String otherName = UUID.randomUUID().toString().replaceAll("-", "")
                + fileName.substring(fileName.lastIndexOf("."));

        return otherName;
    }

    @Test
    public void dd(){
        System.err.println("=---");
    }

}
